const Sprite = require('./Sprite');
/**
 * @class ui界面
 */
class UI extends Sprite {
    constructor(name, color, paint, behavior) {
        super(name, paint, behavior);
        this.color = color || {
            /**底色 */
            bg: '#e1e2e6',
            /**框 */
            line: '#2c2f38',
            /**格子底色 */
            cellBg: '7a7e84',
            /**选中颜色 */
            selectCell: '#fdfdc5',
            /**窗口画轴轴颜色 */
            axisLine: '#6f7278',
            /**画轴画布颜色 */
            axisMain: '#b2b6bf',
            /**红色 */
            red: '#a51a15',
            /**米白色 */
            miwhite: '#fcfcee',
        };
        /**
         * 用于判断鼠标进入哪个元素的
         */
        this._elsPosition = new Map();
        /**
         * 当前鼠标移上或选中的元素名字;
         * close 关闭;
         * role1 - role6 角色;
         */
        this._select = '';
        /**当前选择npc */
        this.currNpc = null;
        /**当前选择的物品 */
        this.currGoods = null;
    }

    /**该方法用来绘制一个有填充色的圆角矩形 
     *@param cxt:canvas的上下文环境 
     *@param x:左上角x轴坐标 
     *@param y:左上角y轴坐标 
     *@param width:矩形的宽度 
     *@param height:矩形的高度 
     *@param radius:圆的半径 
     *@param fillColor:填充颜色 
     **/
    fillRoundRect(cxt, x, y, width, height, radius, /*optional*/ fillColor) {
        //圆的直径必然要小于矩形的宽高          
        if (2 * radius > width || 2 * radius > height) { return false; }

        cxt.save();
        cxt.translate(x, y);
        //绘制圆角矩形的各个边  
        this._drawRoundRectPath(cxt, width, height, radius);
        cxt.fillStyle = fillColor || "#000"; //若是给定了值就用给定的值否则给予默认值  
        cxt.fill();
        cxt.restore();
    }


    /**该方法用来绘制圆角矩形 
     *@param cxt:canvas的上下文环境 
     *@param x:左上角x轴坐标 
     *@param y:左上角y轴坐标 
     *@param width:矩形的宽度 
     *@param height:矩形的高度 
     *@param radius:圆的半径 
     *@param lineWidth:线条粗细 
     *@param strokeColor:线条颜色 
     **/
    strokeRoundRect(cxt, x, y, width, height, radius, /*optional*/ lineWidth, /*optional*/ strokeColor) {
        //圆的直径必然要小于矩形的宽高          
        if (2 * radius > width || 2 * radius > height) { return false; }

        cxt.save();
        cxt.translate(x, y);
        //绘制圆角矩形的各个边  
        this._drawRoundRectPath(cxt, width, height, radius);
        cxt.lineWidth = lineWidth || 2; //若是给定了值就用给定的值否则给予默认值2  
        cxt.strokeStyle = strokeColor || "#000";
        cxt.stroke();
        cxt.restore();
    }

    _drawRoundRectPath(cxt, width, height, radius) {
        cxt.beginPath(0);
        //从右下角顺时针绘制，弧度从0到1/2PI  
        cxt.arc(width - radius, height - radius, radius, 0, Math.PI / 2);

        //矩形下边线  
        cxt.lineTo(radius, height);

        //左下角圆弧，弧度从1/2PI到PI  
        cxt.arc(radius, height - radius, radius, Math.PI / 2, Math.PI);

        //矩形左边线  
        cxt.lineTo(0, radius);

        //左上角圆弧，弧度从PI到3/2PI  
        cxt.arc(radius, radius, radius, Math.PI, Math.PI * 3 / 2);

        //上边线  
        cxt.lineTo(width - radius, 0);

        //右上角圆弧  
        cxt.arc(width - radius, radius, radius, Math.PI * 3 / 2, Math.PI * 2);

        //右边线  
        cxt.lineTo(width, height - radius);
        cxt.closePath();
    }
}

/**
 * @class 主窗口
 */
class WinInterface extends UI {
    constructor(name, title, color, paint, behavior = []) {
        super(name, color, paint, behavior);
        this.title = title;
        this.w = 0;
        this.h = 0;
        this.isMain = false; // 是否是主界面（包含人物，队友等的界面）
        this.layers = null;
        this.games = null;
        this.npc = null;
    }

    /**
     * 遮罩层
     * @function 内部方法
     */
    _mask(ctx, w, h) {
        ctx.save();
        let gd = ctx.createLinearGradient(w / 2, 0, w / 2, h);
        gd.addColorStop(0, '#e0e0e2');
        gd.addColorStop(1, this.color.bg)
        ctx.fillStyle = gd;
        ctx.fillRect(0, 0, w, h);
        ctx.restore();
    }

    /**
     * 将实例作为内部属性,必须最开始调用一次
     * @param {Game} games - Game实例
     * @param {Layer} layers - Layer实例
     */
    add(games, layers) {
        this.layers = layers.ui;
        this.games = games;
        this.w = this.games.w;
        this.h = this.games.h;
        return this;
    }

    /**
     * 选择角色,作为绘制信息对象,将其作为内部对象
     * @param {Character} npc - Character实例
     */
    selectRole(npc) {
        this.npc = npc;
        this.currNpc = this.npc;
        return this;
    }

    /**
     * 打开窗口
     */
    open() {
        // this.isDisplay = true; // 测试用-要还原
        this.layers.ctx.clearRect(0, 0, this.w, this.h);
        this.isMain = true;
        this._draw();
        return this;
    }

    /**
     * 鼠标事件判断
     */
    listenerEl(event) {
        let self = this;
        let els = () => {
            let ev = event || window.event;
            let { pageX, pageY } = ev;

            self._select = '';

            for (let [key, val] of self._elsPosition) {
                if (pageX >= val.x && pageX <= val.x + val.w && pageY >= val.y && pageY <= val.y + val.h) {
                    if (ev.type == 'click') {
                        if (/close/.test(key)) {
                            self.isDisplay = self.isMain = false;
                        }
                        if (/role/.test(key)) {
                            let index = Number(key.match(/\d$/)[0]) - 1;
                            if(index == 0) {
                                self.currNpc = self.npc;
                            } else {
                                self.currNpc = self.npc[index];
                            }
                        }
                    }
                    if (ev.type == 'mousemove') {
                        self._select = key;
                    }
                }
            }

        }
        return els;
    }

    /**
     * 绘制顶栏
     */
    drawTopBar() {
        let w = this.w;
        let h = this.h;
        let npc = this.npc;
        let { ctx } = this.layers;
        let games = this.games;
        this.painter = {
            paint(sprite, ctx) {
                ctx.fillStyle = 'rgba(0, 0, 0, 0.66)';
                ctx.fillRect(0, 0, w, 36);
                // 年月日
                ctx.fillStyle = sprite.color.miwhite;
                ctx.font = 'bold 20px 毛笔字';
                ctx.textBaseline = 'middle';
                ctx.textAlign = 'center';
                ctx.fillText(`${games.year}年-${games.moon}月-${games.day}日`, w / 2, 14);
                // 钱
                ctx.font = 'bold 14px 毛笔字';
                sprite.fillRoundRect(ctx, w - 260, 6, 120, 24, 6, 'rgba(200, 200, 200, .36)');
                ctx.textBaseline = 'middle';
                ctx.textAlign = 'start';
                ctx.fillText(`金钱: ${npc.money}两`, w - 250, 18);
                // 信息
                ctx.font = 'bold 20px 毛笔字';
                ctx.fillText(`${npc.name} ${npc.tags}`, 20, 14);
            }
        };
        this.paint(ctx);
        return this;
    }

    /**
     * 绘制窗口
     * @param {Game} obj - Game的实例
     */
    _draw() {
        if (!this.isDisplay) return this;
        this.w = this.games.w;
        this.h = this.games.h;
        let { ctx } = this.layers;
        let games = this.games;
        let npc = this.npc;
        let x = this.x;
        let y = this.y;
        let w = this.w;
        let h = this.h;
        /**关闭按钮 */
        let drawClosed = sprite => {
            let dw = 36, dh = 36;
            let x1 = w - 100;
            let y1 = 60;
            ctx.beginPath();
            ctx.moveTo(x1, y1);
            ctx.lineTo(x1 + dw / 2, y1 + dh / 2);
            ctx.lineTo(x1, y1 + dh);
            ctx.lineTo(x1 - dw / 2, y1 + dh / 2);
            ctx.closePath();
            ctx.fillStyle = sprite.color.red;
            ctx.fill();
            if (sprite._select == 'close') {
                ctx.strokeStyle = sprite.color.selectCell;
            } else {
                ctx.strokeStyle = '#222';
            }
            ctx.stroke();
            ctx.textAlign = 'center';
            ctx.fillStyle = sprite.color.miwhite;
            ctx.font = '16px 毛笔字';
            ctx.fillText('关闭', x1, y1 + dh / 2);
            if (!sprite._elsPosition.get('close')) {
                sprite._elsPosition.set('close', { x: sprite.w - 118, y: 60, w: 36, h: 36 });
            }
        }
        /**角色窗口 */
        let drawNpcIcon = (sprite, npc, x, y, dw, dh, elname) => {
            let cellw = 100, cellh = 100, diff = 8;
            let x1 = x, y1 = y;
            ctx.save();
            ctx.beginPath();
            ctx.moveTo(x1, y1);
            ctx.lineTo(x1 + cellw / 2, y1 + cellh / 2);
            ctx.lineTo(x1, y1 + cellh);
            ctx.lineTo(x1 - cellw / 2, y1 + cellh / 2);
            ctx.closePath();
            ctx.clip();
            if (sprite._select == elname) {
                ctx.strokeStyle = sprite.color.selectCell;
            } else {
                ctx.fillStyle = '#b3b3b3';
                ctx.strokeStyle = '#222';
            }
            ctx.fill();
            ctx.stroke();
            if (npc) {
                let img = npc.icon instanceof Image ? npc.icon : npc.imgs;
                ctx.drawImage(img, npc.icon.x || 0, npc.icon.y || 0, npc.icon.width, npc.icon.height, (w - dw) / 2 + diff + cellw * .1, (h - dh) / 2 + diff + cellh * .1, cellw * 0.8, cellh * 0.8);
                ctx.fillStyle = 'rgba(0, 0, 0, .42)';
                ctx.fillRect(x1 - cellw / 2, y1 + cellh * 3 / 4, cellw, cellh);
                ctx.textAlign = 'center';
                ctx.font = '10px 毛笔字';
                ctx.fillStyle = sprite.color.miwhite;
                ctx.restore();
                let fontWidth = ctx.measureText(npc.name).width;
                ctx.fillText(npc.name, x1 - cellw / 2 + fontWidth, y1 + cellh * 3 / 4 + 8);
            } else {
                ctx.restore();
            }
            if (!sprite._elsPosition.get(elname)) {
                sprite._elsPosition.set(elname, { x: x1 - cellw / 2, y: y1, w: 100, h: 100 });
            }
        }
        /**绘制主体/画轴 */
        let drawAxis = (sprite, dw, dh) => {
            ctx.fillStyle = '#222';
            ctx.fillRect((w - dw) / 2 - 20, (h - dh) / 2 - 7, dw + 40, 6);
            ctx.fillStyle = sprite.color.axisLine;
            ctx.fillRect((w - dw) / 2 - 12, (h - dh) / 2 - 8, dw + 24, 8);
            ctx.strokeStyle = '#222';
            ctx.strokeRect((w - dw) / 2 - 12, (h - dh) / 2 - 8, dw + 24, 8);
            ctx.fillStyle = sprite.color.axisMain;
            ctx.fillRect((w - dw) / 2, (h - dh) / 2, dw, dh);
            ctx.strokeStyle = '#222';
            ctx.strokeRect((w - dw) / 2, (h - dh) / 2, dw, dh);
            ctx.fillRect((w - dw) / 2 - 8, dh + (h - dh) / 2 - 2, dw + 16, 4);
            ctx.strokeRect((w - dw) / 2 - 8, dh + (h - dh) / 2 - 2, dw + 16, 4);
            ctx.fillStyle = sprite.color.axisLine;
            ctx.fillRect((w - dw) / 2 - 10, dh + (h - dh) / 2 + 2, dw + 20, 4);
            ctx.strokeRect((w - dw) / 2 - 10, dh + (h - dh) / 2 + 2, dw + 20, 4);
        }
        this.painter = {
            paint(sprite, ctx) {
                sprite._mask(ctx, w, h);
                ctx.shadowColor = 'rgba(0, 0, 0, .72)';
                ctx.shadowBlur = 6;
                ctx.shadowOffsetX = 3;
                ctx.shadowOffsetY = 3;
                let dh = h * 0.8;
                let dw = dh * 1.8;
                drawAxis(sprite, dw, dh);
                drawClosed(sprite);
                if (sprite.isMain) {
                    ctx.shadowBlur = 2;
                    ctx.shadowOffsetX = 1;
                    ctx.shadowOffsetY = 2;
                    let cellw = 100, cellh = 100, diff = 16;
                    let x1 = (w - dw) / 2 + diff + cellw / 2, y1 = (h - dh) / 2 + diff;
                    drawNpcIcon(sprite, npc, x1, y1, dw, dh, 'role1');
                    let dx = 0, dy = 0;
                    npc.team.map((el, index) => {
                        switch (index) {
                            case 0:
                                dx = x1 + cellw / 2 + diff;
                                dy = y1 + cellh / 2 + diff;
                                drawNpcIcon(sprite, el, dx, dy, cellw, cellh, 'role2');
                                break;
                            case 1:
                                dx = dx - cellw / 2 - diff;
                                dy = dy + cellh / 2 + diff;
                                drawNpcIcon(sprite, el, dx, dy, cellw, cellh, 'role3');
                                break;
                            case 2:
                                dx = dx + cellw / 2 + diff;
                                dy = dy + cellh / 2 + diff;
                                drawNpcIcon(sprite, el, dx, dy, cellw, cellh, 'role4');
                                break;
                            case 3:
                                dx = dx - cellw / 2 - diff;
                                dy = dy + cellh / 2 + diff;
                                drawNpcIcon(sprite, el, dx, dy, cellw, cellh, 'role5');
                                break;
                            case 4:
                                dx = dx + cellw / 2 + diff;
                                dy = dy + cellh / 2 + diff;
                                drawNpcIcon(sprite, el, dx, dy, cellw, cellh, 'role6');
                                break;
                        }
                    })
                }
            }
        };
        this.paint(ctx);
        return this;
    }
}

module.exports = {
    UI, 
    WinInterface,
}